#ifndef _PROPERTIES_H_
#define _PROPERTIES_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "engine/ArrayList.hh"

using namespace std;

class Properties {
public:

    class Property {
    private:
        char * key;
        char * value;
    public:
        Property() {
            key = NULL;
            value = NULL;
        }

        Property(char *key, char *value) {
            this->key = key;
            this->value = value;
        }

        ~Property() {
            if (key != NULL) delete [] key;

            if (value != NULL) delete [] value;
        }

        void setKey(char *key) {
            this->key = key;
        }

        char *getKey() {
            return key;
        }

        void setValue(char *value) {
            this->value = value;
        }

        char *getValue() {
            return value;
        }
    };

private:
    ArrayList<Property> *list;

public:
    Properties() {
        list = new ArrayList<Property>(true);
    }

    ~Properties() {
        delete list;
    }

    static Properties *load(char *fileName) {
        FILE *file = fopen(fileName, "r");

        if (file == NULL) {
            cout << "the file " << fileName <<" could not be open, aborting..." << endl;
            exit(1);

        }

        int lineNumber = 0;
        Properties* properties = new Properties();
        char *line = NULL;

        while (feof(file) == 0) {
            line = readLine(file);
            lineNumber++;

            if (strlen(line) > 1 && line[0] != '#' && line[0] != '\n') {

                char *bufferKey = new char[100];
                memset(bufferKey, 0, 100);
                char *bufferValue = new char[100];
                memset(bufferValue, 0, 100);

                sscanf(line, "%100s%100s", bufferKey, bufferValue);

                if (strlen(bufferKey) + strlen(bufferValue) == 0) {
                    cout << "missing data on line %d, aborting..." << endl;
                    exit(1);
                }

                properties->put(bufferKey, bufferValue);
            }

            delete[] line;
            line = NULL;
        }

        fclose(file);
        return properties;
    }

    char *get(char *key, char *defaultValue) {
        Property* property = NULL;

        for (int i = 0; i < list->length(); i++) {
            property = list->get(i);

            if (strlen(key) == strlen(property->getKey()) && strcmp(key, property->getKey()) == 0)
                return property->getValue();

        }

        cout << endl << "***************warning" << endl
             << key << " not found using default value " << defaultValue << endl;

        return defaultValue;
    }

    void put(char *key, char *value) {
        Property *property = new Property(key, value);
        int idx = -1;

        for (int i = 0; i < list->length(); i++) {
            if (strcmp(key, list->get(i)->getKey()) == 0) {
                idx = i;
                break;
            }

        }

        if (idx != -1) {
            list->remove(idx);
            list->add(property);

        } else list->add(property);
    }

    int length() {
        return list->length();
    }

    char* getKey(int idx) {
        return list->get(idx)->getKey();
    }

    char* getValue(int idx) {
        return list->get(idx)->getValue();
    }

private:
    static char *readLine(FILE *file) {
        char *buffer = new char[200];
        bzero(buffer, 200);
        int i = 0;

        while (feof(file) == 0) {
            char c = fgetc(file);
            buffer[i] = c;
            i++;

            if (c == '\n') break;
        }

        return buffer;
    }

};

#endif
